package com.socialsoftware.Page;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.socialsoftware.api.ApiError;
import com.socialsoftware.api.ApiService;
import com.socialsoftware.databinding.ActivityQrScannerBinding;
import com.socialsoftware.model.Contact;
import com.socialsoftware.util.SessionManager;

import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class QRScannerActivity extends AppCompatActivity {
    private static final int CAMERA_PERMISSION_REQUEST_CODE = 100;
    private ActivityQrScannerBinding binding;
    private ExecutorService cameraExecutor;
    private ApiService apiService;
    
    // Variables to prevent duplicate processing
    private boolean isProcessingQRCode = false;
    private String lastProcessedQRCode = "";
    private long lastProcessedTimestamp = 0;
    private static final long DEBOUNCE_TIME_MS = 2000; // 2 seconds debounce

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityQrScannerBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // Initialize API service
        apiService = new ApiService(SessionManager.getInstance(this));

        // Set up the back button
        binding.backButton.setOnClickListener(v -> finish());

        // Check camera permissions
        if (allPermissionsGranted()) {
            startCamera();
        } else {
            ActivityCompat.requestPermissions(this, 
                    new String[]{Manifest.permission.CAMERA}, 
                    CAMERA_PERMISSION_REQUEST_CODE);
        }

        cameraExecutor = Executors.newSingleThreadExecutor();
    }

    private boolean allPermissionsGranted() {
        return ContextCompat.checkSelfPermission(
                this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
            if (allPermissionsGranted()) {
                startCamera();
            } else {
                Toast.makeText(this, "需要相机权限来扫描二维码", Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    private void startCamera() {
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);

        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

                Preview preview = new Preview.Builder().build();
                preview.setSurfaceProvider(binding.previewView.getSurfaceProvider());

                CameraSelector cameraSelector = new CameraSelector.Builder()
                        .requireLensFacing(CameraSelector.LENS_FACING_BACK)
                        .build();

                ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                        .build();

                imageAnalysis.setAnalyzer(cameraExecutor, new QRCodeAnalyzer());

                // Unbind any bound use cases before rebinding
                cameraProvider.unbindAll();

                // Bind use cases to camera
                Camera camera = cameraProvider.bindToLifecycle(
                        this, cameraSelector, preview, imageAnalysis);

                // Enable flash if available
                binding.flashButton.setOnClickListener(v -> {
                    if (camera.getCameraInfo().hasFlashUnit()) {
                        boolean isTorchOn = camera.getCameraInfo().getTorchState().getValue() == 1;
                        camera.getCameraControl().enableTorch(!isTorchOn);
                    } else {
                        Toast.makeText(this, "闪光灯不可用", Toast.LENGTH_SHORT).show();
                    }
                });

            } catch (ExecutionException | InterruptedException e) {
                Toast.makeText(this, "无法启动相机: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        }, ContextCompat.getMainExecutor(this));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cameraExecutor.shutdown();
    }

    private class QRCodeAnalyzer implements ImageAnalysis.Analyzer {
        private final MultiFormatReader multiFormatReader = new MultiFormatReader();

        @Override
        public void analyze(@NonNull ImageProxy image) {
            // Skip processing if we're already handling a QR code
            if (isProcessingQRCode) {
                image.close();
                return;
            }
            
            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            byte[] data = new byte[buffer.remaining()];
            buffer.get(data);

            PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
                    data,
                    image.getWidth(),
                    image.getHeight(),
                    0,
                    0,
                    image.getWidth(),
                    image.getHeight(),
                    false
            );

            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            try {
                Result result = multiFormatReader.decode(bitmap);
                String scannedText = result.getText();
                
                // Check if this is a duplicate scan or if we need to debounce
                long currentTime = System.currentTimeMillis();
                if (scannedText.equals(lastProcessedQRCode) && 
                    currentTime - lastProcessedTimestamp < DEBOUNCE_TIME_MS) {
                    // Skip duplicate scan within debounce time
                    image.close();
                    return;
                }
                
                // Update tracking variables
                lastProcessedQRCode = scannedText;
                lastProcessedTimestamp = currentTime;
                isProcessingQRCode = true;
                
                // Show scanning indicator
                runOnUiThread(() -> {
                    binding.scanningIndicator.setVisibility(View.VISIBLE);
                });
                
                // Process the scanned QR code
                processQRCode(scannedText);
                
            } catch (NotFoundException e) {
                // QR code not found in this frame, continue scanning
            } finally {
                image.close();
            }
        }
    }
    
    private void processQRCode(String qrContent) {
        runOnUiThread(() -> {
            try {
                // Try to parse as JSON
                JsonObject jsonObject = JsonParser.parseString(qrContent).getAsJsonObject();
                
                // Check if it's a friend request QR code
                if (jsonObject.has("type") && "friend_request".equals(jsonObject.get("type").getAsString())) {
                    if (jsonObject.has("username")) {
                        String username = jsonObject.get("username").getAsString();
                        searchUserAndShowFriendRequest(username);
                    } else {
                        Toast.makeText(QRScannerActivity.this, 
                                "二维码格式无效，缺少用户名", Toast.LENGTH_SHORT).show();
                        resetProcessingState();
                    }
                } else {
                    // Handle as a regular QR code
                    handleRegularQRCode(qrContent);
                }
            } catch (JsonSyntaxException e) {
                // Not a JSON format, handle as a regular QR code
                handleRegularQRCode(qrContent);
            }
        });
    }
    
    private void searchUserAndShowFriendRequest(String username) {
        Toast.makeText(this, "正在查找用户: " + username, Toast.LENGTH_SHORT).show();
        
        // Search for the user by username
        apiService.searchFriends(username, "qrcode", new ApiService.ApiCallback<List<Contact>>() {
            @Override
            public void onSuccess(List<Contact> results) {
                runOnUiThread(() -> {
                    if (results != null && !results.isEmpty()) {
                        // User found, open friend request activity
                        Contact contact = results.get(0);
                        navigateToFriendRequest(contact);
                    } else {
                        // User not found
                        Toast.makeText(QRScannerActivity.this, 
                                "未找到用户: " + username, Toast.LENGTH_SHORT).show();
                        resetProcessingState();
                    }
                });
            }
            
            @Override
            public void onFailure(ApiError error) {
                runOnUiThread(() -> {
                    Toast.makeText(QRScannerActivity.this, 
                            "查找用户失败: " + error.getMessage(), Toast.LENGTH_SHORT).show();
                    
                    // Create a mock contact for testing purposes
                    Contact mockContact = new Contact(username, username, "avatar_default");
                    navigateToFriendRequest(mockContact);
                });
            }
        });
    }
    
    private void navigateToFriendRequest(Contact contact) {
        Intent intent = new Intent(QRScannerActivity.this, FriendRequestActivity.class);
        intent.putExtra("contact", contact);
        intent.putExtra("from_qr_scan", true); // Flag to indicate this came from QR scan
        startActivity(intent);
        finish(); // Close the scanner activity
    }
    
    private void handleRegularQRCode(String qrContent) {
        // Return the scanned result to the calling activity
        Intent resultIntent = new Intent();
        resultIntent.putExtra("SCAN_RESULT", qrContent);
        setResult(RESULT_OK, resultIntent);
        
        // Show a toast with the result
        Toast.makeText(QRScannerActivity.this, 
                "扫描结果: " + qrContent, 
                Toast.LENGTH_SHORT).show();
        
        finish();
    }
    
    private void resetProcessingState() {
        // Hide the scanning indicator
        binding.scanningIndicator.setVisibility(View.GONE);
        
        // Reset processing state after a delay
        binding.scanningIndicator.postDelayed(() -> {
            isProcessingQRCode = false;
        }, 1000); // Give a second before allowing new scans
    }
} 